package main

import (
	"context"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/pkg/sftp"
	wailsRuntime "github.com/wailsapp/wails/v2/pkg/runtime"
	"golang.org/x/crypto/ssh"
)

// App 应用结构体
type App struct {
	ctx context.Context
	// 终端防重复打开的变量
	terminalBusy     bool
	lastTerminalHost string
	lastTerminalTime time.Time
}

// NewApp 创建新的App实例
func NewApp() *App {
	return &App{}
}

// startup 应用启动时调用
func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
	log.Println("应用启动")
}

// domReady DOM加载完成时调用
func (a *App) domReady(ctx context.Context) {
	log.Println("DOM加载完成")
}

// shutdown 应用关闭时调用
func (a *App) shutdown(ctx context.Context) {
	log.Println("应用关闭")
}

// logInfo 记录信息日志
func (a *App) logInfo(format string, args ...interface{}) {
	message := fmt.Sprintf(format, args...)
	log.Printf("[INFO] %s", message)
	if a.ctx != nil {
		wailsRuntime.LogInfo(a.ctx, message)
	}
}

// logError 记录错误日志
func (a *App) logError(format string, args ...interface{}) {
	message := fmt.Sprintf(format, args...)
	log.Printf("[ERROR] %s", message)
	if a.ctx != nil {
		wailsRuntime.LogError(a.ctx, message)
	}
}

// CheckSSHKeys 检查本地SSH密钥状态
func (a *App) CheckSSHKeys() map[string]interface{} {
	homeDir, err := os.UserHomeDir()
	if err != nil {
		a.logError("获取用户目录失败: %v", err)
		return map[string]interface{}{
			"privateKeyExists": false,
			"publicKeyExists":  false,
			"privateKeyPath":   "",
			"publicKeyPath":    "",
			"error":            fmt.Sprintf("获取用户目录失败: %v", err),
		}
	}

	sshDir := filepath.Join(homeDir, ".ssh")
	privateKeyPath := filepath.Join(sshDir, "id_rsa")
	publicKeyPath := filepath.Join(sshDir, "id_rsa.pub")

	privateKeyExists := fileExists(privateKeyPath)
	publicKeyExists := fileExists(publicKeyPath)

	return map[string]interface{}{
		"privateKeyExists": privateKeyExists,
		"publicKeyExists":  publicKeyExists,
		"privateKeyPath":   privateKeyPath,
		"publicKeyPath":    publicKeyPath,
	}
}

// GenerateSSHKeys 生成新的SSH密钥对
func (a *App) GenerateSSHKeys() map[string]interface{} {
	a.logInfo("正在生成SSH密钥对...")

	// 创建.ssh目录
	homeDir, err := os.UserHomeDir()
	if err != nil {
		a.logError("获取用户目录失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("获取用户目录失败: %v", err),
		}
	}

	sshDir := filepath.Join(homeDir, ".ssh")
	err = os.MkdirAll(sshDir, 0700)
	if err != nil {
		a.logError("创建.ssh目录失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("创建.ssh目录失败: %v", err),
		}
	}

	// 生成RSA密钥对 - 使用4096位长度提高安全性
	// 注：4096位提供更高的安全性，但兼容性仍然良好
	a.logInfo("生成RSA-4096密钥对，提供更高安全性")
	privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
	if err != nil {
		a.logError("生成RSA密钥对失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("生成RSA密钥对失败: %v", err),
		}
	}

	// 将私钥编码为PEM格式
	privateKeyPEM := &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
	}

	privateKeyPath := filepath.Join(sshDir, "id_rsa")
	privateKeyFile, err := os.OpenFile(privateKeyPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		a.logError("创建私钥文件失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("创建私钥文件失败: %v", err),
		}
	}
	defer privateKeyFile.Close()

	err = pem.Encode(privateKeyFile, privateKeyPEM)
	if err != nil {
		a.logError("写入私钥文件失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("写入私钥文件失败: %v", err),
		}
	}

	// 生成公钥
	publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey)
	if err != nil {
		a.logError("生成SSH公钥失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("生成SSH公钥失败: %v", err),
		}
	}

	publicKeyBytes := ssh.MarshalAuthorizedKey(publicKey)
	publicKeyPath := filepath.Join(sshDir, "id_rsa.pub")
	err = os.WriteFile(publicKeyPath, publicKeyBytes, 0644)
	if err != nil {
		a.logError("写入公钥文件失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("写入公钥文件失败: %v", err),
		}
	}

	// 也可以使用系统ssh-keygen命令生成密钥（备用方案）
	// cmd := exec.Command("ssh-keygen", "-t", "rsa", "-b", "4096", "-f", privateKeyPath, "-N", "")
	// cmd.Stdout = os.Stdout
	// cmd.Stderr = os.Stderr
	// if cmd.Run() != nil {
	//     a.logError("使用ssh-keygen生成密钥失败，返回使用Go原生生成的密钥")
	// }

	a.logInfo("SSH密钥对生成成功")
	return map[string]interface{}{
		"success":        true,
		"message":        "SSH密钥对(RSA-4096)生成成功",
		"privateKeyPath": privateKeyPath,
		"publicKeyPath":  publicKeyPath,
	}
}

// DeleteSSHKeys 删除SSH密钥
func (a *App) DeleteSSHKeys() map[string]interface{} {
	a.logInfo("正在删除SSH密钥...")

	homeDir, err := os.UserHomeDir()
	if err != nil {
		a.logError("获取用户目录失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("获取用户目录失败: %v", err),
		}
	}

	sshDir := filepath.Join(homeDir, ".ssh")
	privateKeyPath := filepath.Join(sshDir, "id_rsa")
	publicKeyPath := filepath.Join(sshDir, "id_rsa.pub")

	// 删除私钥
	if fileExists(privateKeyPath) {
		err = os.Remove(privateKeyPath)
		if err != nil {
			a.logError("删除私钥文件失败: %v", err)
			return map[string]interface{}{
				"success": false,
				"message": fmt.Sprintf("删除私钥文件失败: %v", err),
			}
		}
	}

	// 删除公钥
	if fileExists(publicKeyPath) {
		err = os.Remove(publicKeyPath)
		if err != nil {
			a.logError("删除公钥文件失败: %v", err)
			return map[string]interface{}{
				"success": false,
				"message": fmt.Sprintf("删除公钥文件失败: %v", err),
			}
		}
	}

	a.logInfo("SSH密钥删除成功")
	return map[string]interface{}{
		"success": true,
		"message": "SSH密钥删除成功",
	}
}

// ImportSSHKey 导入已有的SSH密钥
func (a *App) ImportSSHKey() map[string]interface{} {
	a.logInfo("正在导入SSH密钥...")

	// 打开文件选择器
	dialogOptions := wailsRuntime.OpenDialogOptions{
		Title: "选择SSH私钥文件",
		Filters: []wailsRuntime.FileFilter{
			{
				DisplayName: "SSH私钥文件",
				Pattern:     "*",
			},
		},
	}

	filePath, err := wailsRuntime.OpenFileDialog(a.ctx, dialogOptions)
	if err != nil {
		a.logError("打开文件对话框失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("打开文件对话框失败: %v", err),
		}
	}

	if filePath == "" {
		return map[string]interface{}{
			"success": false,
			"message": "未选择文件",
		}
	}

	// 读取选中的私钥文件
	keyData, err := os.ReadFile(filePath)
	if err != nil {
		a.logError("读取私钥文件失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("读取私钥文件失败: %v", err),
		}
	}

	// 验证是否为有效的私钥文件
	block, _ := pem.Decode(keyData)
	if block == nil || block.Type != "RSA PRIVATE KEY" {
		a.logError("文件不是有效的RSA私钥格式")
		return map[string]interface{}{
			"success": false,
			"message": "文件不是有效的RSA私钥格式",
		}
	}

	// 创建.ssh目录
	homeDir, err := os.UserHomeDir()
	if err != nil {
		a.logError("获取用户目录失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("获取用户目录失败: %v", err),
		}
	}

	sshDir := filepath.Join(homeDir, ".ssh")
	err = os.MkdirAll(sshDir, 0700)
	if err != nil {
		a.logError("创建.ssh目录失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("创建.ssh目录失败: %v", err),
		}
	}

	// 复制私钥到id_rsa文件
	privateKeyPath := filepath.Join(sshDir, "id_rsa")
	err = os.WriteFile(privateKeyPath, keyData, 0600)
	if err != nil {
		a.logError("保存私钥文件失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("保存私钥文件失败: %v", err),
		}
	}

	// 从私钥生成公钥
	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		a.logError("解析私钥失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("解析私钥失败: %v", err),
		}
	}

	publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey)
	if err != nil {
		a.logError("生成公钥失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("生成公钥失败: %v", err),
		}
	}

	publicKeyBytes := ssh.MarshalAuthorizedKey(publicKey)
	publicKeyPath := filepath.Join(sshDir, "id_rsa.pub")
	err = os.WriteFile(publicKeyPath, publicKeyBytes, 0644)
	if err != nil {
		a.logError("保存公钥文件失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("保存公钥文件失败: %v", err),
		}
	}

	a.logInfo("SSH密钥导入成功")
	return map[string]interface{}{
		"success": true,
		"message": "SSH密钥导入成功",
	}
}

// 辅助函数：检查文件是否存在
func fileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

// ConfigureSSH 纯Go实现上传公钥（无任何cmd调用）
func (a *App) ConfigureSSH(host string, port string, username string, password string, disablePassword bool) map[string]interface{} {
	a.logInfo("配置SSH服务: %s@%s:%s, 禁用密码登录: %v", username, host, port, disablePassword)

	// 1. 安全检查 - 验证输入参数
	if host == "" || username == "" || password == "" {
		a.logError("参数不完整: 需要主机名、用户名和密码")
		return map[string]interface{}{
			"success": false,
			"message": "参数不完整，请确保填写了主机名、用户名和密码",
		}
	}

	// 设置默认端口
	if port == "" {
		port = "22"
	}

	// 2. 读取本地公钥
	homeDir, err := os.UserHomeDir()
	if err != nil {
		a.logError("获取用户目录失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("获取用户目录失败: %v", err),
		}
	}

	publicKeyPath := filepath.Join(homeDir, ".ssh", "id_rsa.pub")
	publicKeyData, err := os.ReadFile(publicKeyPath)
	if err != nil {
		a.logError("读取公钥文件失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("读取公钥文件失败: %v", err),
		}
	}
	publicKey := strings.TrimSpace(string(publicKeyData))
	a.logInfo("成功读取本地公钥，长度: %d 字节", len(publicKey))

	// 验证公钥格式
	if !strings.HasPrefix(publicKey, "ssh-") && !strings.Contains(publicKey, " ") {
		a.logError("公钥格式无效")
		return map[string]interface{}{
			"success": false,
			"message": "公钥格式无效，请确保它是标准的OpenSSH公钥格式",
		}
	}

	// 3. 建立加密的SSH连接
	a.logInfo("正在尝试与服务器建立SSH连接...")
	sshConfig := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 注意：生产环境应使用FixedHostKey或其他验证方法
		Timeout:         10 * time.Second,
	}

	// 记录连接尝试但不包含敏感信息
	a.logInfo("正在连接到服务器 %s:%s", host, port)
	sshAddr := fmt.Sprintf("%s:%s", host, port)
	sshClient, err := ssh.Dial("tcp", sshAddr, sshConfig)
	if err != nil {
		a.logError("SSH连接失败: %v", err)

		// 提供更具体的错误信息
		errorMsg := fmt.Sprintf("SSH连接失败: %v", err)
		if strings.Contains(err.Error(), "unable to authenticate") {
			errorMsg = "认证失败: 请检查用户名和密码是否正确"
		} else if strings.Contains(err.Error(), "connection refused") {
			errorMsg = "连接被拒绝: 请检查SSH服务是否运行，以及主机和端口是否正确"
		} else if strings.Contains(err.Error(), "timeout") {
			errorMsg = "连接超时: 请检查网络状况和防火墙设置"
		}

		return map[string]interface{}{
			"success": false,
			"message": errorMsg,
		}
	}
	defer sshClient.Close()
	a.logInfo("SSH连接建立成功")

	// 4. 检查远程环境
	// 首先获取远程主目录信息
	a.logInfo("获取远程用户环境信息...")
	envSession, err := sshClient.NewSession()
	if err != nil {
		a.logError("创建SSH会话获取环境信息失败: %v", err)
	} else {
		defer envSession.Close()
		// 获取环境变量和系统信息
		envCmd := "echo \"HOME=$HOME\"; echo \"USER=$USER\"; echo \"PWD=$(pwd)\"; echo \"OSTYPE=$(uname -a)\""
		envOutput, _ := envSession.CombinedOutput(envCmd)
		a.logInfo("远程环境信息: %s", string(envOutput))
	}

	// 5. 创建SFTP客户端用于安全文件传输
	a.logInfo("正在创建SFTP客户端")
	sftpClient, err := sftp.NewClient(sshClient)
	if err != nil {
		a.logError("SFTP创建失败: %v，尝试使用SSH命令直接操作", err)
		// 如果SFTP失败，我们继续使用普通SSH命令
	} else {
		defer sftpClient.Close()
		a.logInfo("SFTP客户端创建成功")
	}

	// 使用SSH会话获取用户主目录的完整路径
	userHomeSession, err := sshClient.NewSession()
	if err != nil {
		a.logError("创建SSH会话获取用户主目录失败: %v", err)
	} else {
		defer userHomeSession.Close()
		homeOutput, _ := userHomeSession.Output("echo $HOME")
		if len(homeOutput) > 0 {
			remoteHomeDir := strings.TrimSpace(string(homeOutput))
			a.logInfo("远程用户主目录: %s", remoteHomeDir)
		}
	}

	// 6. 确保目标目录存在并设置安全权限
	a.logInfo("确保远程.ssh目录存在...")
	// 使用SSH命令直接创建目录并设置权限
	mkdirSession, err := sshClient.NewSession()
	if err != nil {
		a.logError("创建SSH会话创建目录失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("创建SSH会话失败: %v", err),
		}
	}
	defer mkdirSession.Close()

	// 使用SSH命令创建.ssh目录并设置权限
	mkdirCmd := "mkdir -p ~/.ssh && chmod 700 ~/.ssh && ls -la ~/.ssh"
	mkdirOutput, err := mkdirSession.CombinedOutput(mkdirCmd)
	if err != nil {
		a.logError("创建.ssh目录失败: %v, 输出: %s", err, string(mkdirOutput))
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("创建.ssh目录失败: %v", err),
		}
	}
	a.logInfo(".ssh目录创建结果: %s", string(mkdirOutput))

	// 7. 检查远程.ssh目录内容
	lsSession, err := sshClient.NewSession()
	if err != nil {
		a.logError("创建SSH会话检查目录内容失败: %v", err)
	} else {
		defer lsSession.Close()
		lsCmd := "ls -la ~/.ssh"
		lsOutput, _ := lsSession.CombinedOutput(lsCmd)
		a.logInfo("远程.ssh目录内容:\n%s", string(lsOutput))
	}

	// 8. 直接使用SSH命令上传公钥
	a.logInfo("正在使用SSH命令上传公钥...")
	pubKeySession, err := sshClient.NewSession()
	if err != nil {
		a.logError("创建SSH会话上传公钥失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("创建SSH会话上传公钥失败: %v", err),
		}
	}
	defer pubKeySession.Close()

	// 处理公钥中的特殊字符，确保命令正确执行
	escapedPublicKey := strings.Replace(publicKey, "'", "'\\''", -1)

	// 先检查是否已存在相同公钥
	checkCmd := fmt.Sprintf("grep -q '%s' ~/.ssh/authorized_keys 2>/dev/null && echo '公钥已存在' || echo '公钥不存在'", escapedPublicKey)
	checkSession, err := sshClient.NewSession()
	if err == nil {
		defer checkSession.Close()
		checkOutput, _ := checkSession.CombinedOutput(checkCmd)
		a.logInfo("检查公钥: %s", string(checkOutput))
	}

	// 使用追加方式写入公钥，创建文件如果不存在
	pubKeyCmd := fmt.Sprintf("echo '%s' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys && echo '公钥已添加'", escapedPublicKey)
	pubKeyOutput, err := pubKeySession.CombinedOutput(pubKeyCmd)
	if err != nil {
		a.logError("添加公钥到authorized_keys失败: %v, 输出: %s", err, string(pubKeyOutput))
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("添加公钥失败: %v", err),
		}
	}
	a.logInfo("公钥上传结果: %s", string(pubKeyOutput))

	// 9. 验证公钥是否确实添加成功
	verifySession, err := sshClient.NewSession()
	if err != nil {
		a.logError("创建SSH会话验证公钥失败: %v", err)
	} else {
		defer verifySession.Close()
		verifyCmd := "cat ~/.ssh/authorized_keys | wc -l"
		verifyOutput, _ := verifySession.CombinedOutput(verifyCmd)
		a.logInfo("authorized_keys行数: %s", string(verifyOutput))

		// 显示authorized_keys内容以进行确认
		catSession, err := sshClient.NewSession()
		if err == nil {
			defer catSession.Close()
			catOutput, _ := catSession.CombinedOutput("cat ~/.ssh/authorized_keys")
			keyContent := string(catOutput)
			if len(keyContent) > 100 {
				keyPreview := keyContent[:50] + "..." + keyContent[len(keyContent)-50:]
				a.logInfo("authorized_keys内容预览: %s", keyPreview)
			} else {
				a.logInfo("authorized_keys完整内容: %s", keyContent)
			}
		}
	}

	// 10. 检查并修改SSH配置文件以确保启用公钥认证
	a.logInfo("修改SSH服务器配置")
	session, err := sshClient.NewSession()
	if err != nil {
		a.logError("创建SSH会话失败: %v", err)
		return map[string]interface{}{
			"success": true, // 公钥已经上传成功，但无法修改配置
			"message": fmt.Sprintf("公钥上传成功，但无法创建SSH会话修改配置: %v", err),
		}
	}
	defer session.Close()

	// 构建一个修改SSH配置的脚本，添加错误处理
	configScript := fmt.Sprintf(`
	echo "正在检查并修改SSH配置..."
	
	# 查找sshd_config文件
	SSHD_CONFIG_PATH=""
	for p in /etc/ssh/sshd_config /usr/local/etc/ssh/sshd_config /usr/local/etc/sshd_config; do
		if [ -f "$p" ]; then
			SSHD_CONFIG_PATH="$p"
			break
		fi
	done
	
	if [ -z "$SSHD_CONFIG_PATH" ]; then
		echo "错误: 找不到sshd_config文件"
		exit 1
	fi
	
	echo "找到SSH配置文件: $SSHD_CONFIG_PATH"
	
	# 检查文件是否可写
	if [ ! -w "$SSHD_CONFIG_PATH" ] && ! sudo -n test -w "$SSHD_CONFIG_PATH" 2>/dev/null; then
		echo "警告: SSH配置文件不可写，将尝试使用sudo"
	fi
	
	# 创建一个函数来安全地修改配置
	modify_config() {
		local pattern="$1"
		local replacement="$2"
		local config="$3"
		
		# 尝试使用sudo获取备份
		echo '%s' | sudo -S cp "$config" "${config}.bak.$(date +%%Y%%m%%d_%%H%%M%%S)" 2>/dev/null || true
		
		# 尝试直接修改或使用sudo
		if [ -w "$config" ]; then
			sed -i "$pattern" "$config" 2>/dev/null && echo "直接修改成功: $replacement" || echo "直接修改失败: $pattern"
		else
			echo '%s' | sudo -S sed -i "$pattern" "$config" 2>/dev/null && echo "使用sudo修改成功: $replacement" || echo "使用sudo修改失败: $pattern"
		fi
	}
	
	# 确保PubkeyAuthentication为yes（关键配置）
	if grep -q '^PubkeyAuthentication' "$SSHD_CONFIG_PATH"; then
		modify_config 's/^PubkeyAuthentication.*/PubkeyAuthentication yes/' "PubkeyAuthentication yes" "$SSHD_CONFIG_PATH"
	else
		echo '%s' | sudo -S bash -c "echo 'PubkeyAuthentication yes' >> $SSHD_CONFIG_PATH" 2>/dev/null || echo "添加PubkeyAuthentication失败"
	fi
	
	# 确保AuthorizedKeysFile包含标准路径
	if ! grep -q '^AuthorizedKeysFile' "$SSHD_CONFIG_PATH"; then
		echo '%s' | sudo -S bash -c "echo 'AuthorizedKeysFile .ssh/authorized_keys' >> $SSHD_CONFIG_PATH" 2>/dev/null || echo "添加AuthorizedKeysFile失败"
	fi
	
	# 确保SSH服务器接受RSA密钥（某些新版SSH默认禁用）
	if grep -q '^PubkeyAcceptedKeyTypes\|^PubkeyAcceptedAlgorithms' "$SSHD_CONFIG_PATH"; then
		if ! grep -q 'ssh-rsa' "$SSHD_CONFIG_PATH"; then
			modify_config 's/^\\(PubkeyAcceptedKeyTypes\\|PubkeyAcceptedAlgorithms\\).*/\\1 ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-ed25519,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521/' \
				"添加RSA算法支持" "$SSHD_CONFIG_PATH"
		fi
	else
		echo '%s' | sudo -S bash -c "echo 'PubkeyAcceptedKeyTypes ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-ed25519,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521' >> $SSHD_CONFIG_PATH" \
			2>/dev/null || echo "添加PubkeyAcceptedKeyTypes失败"
	fi
	
	# 启用RSAAuthentication（老版本SSH需要）
	if ! grep -q '^RSAAuthentication' "$SSHD_CONFIG_PATH"; then
		echo '%s' | sudo -S bash -c "echo 'RSAAuthentication yes' >> $SSHD_CONFIG_PATH" 2>/dev/null || echo "添加RSAAuthentication失败"
	else
		modify_config 's/^RSAAuthentication.*/RSAAuthentication yes/' "RSAAuthentication yes" "$SSHD_CONFIG_PATH"
	fi
	
	# 如果需要，禁用密码登录
	if [ "%v" = "true" ]; then
		echo "正在禁用密码登录..."
		if grep -q '^PasswordAuthentication' "$SSHD_CONFIG_PATH"; then
			modify_config 's/^PasswordAuthentication.*/PasswordAuthentication no/' "PasswordAuthentication no" "$SSHD_CONFIG_PATH"
		else
			echo '%s' | sudo -S bash -c "echo 'PasswordAuthentication no' >> $SSHD_CONFIG_PATH" 2>/dev/null || echo "添加PasswordAuthentication失败"
		fi
		
		if grep -q '^ChallengeResponseAuthentication' "$SSHD_CONFIG_PATH"; then
			modify_config 's/^ChallengeResponseAuthentication.*/ChallengeResponseAuthentication no/' "ChallengeResponseAuthentication no" "$SSHD_CONFIG_PATH"
		else
			echo '%s' | sudo -S bash -c "echo 'ChallengeResponseAuthentication no' >> $SSHD_CONFIG_PATH" 2>/dev/null || echo "添加ChallengeResponseAuthentication失败"
		fi
	fi
	
	# 检查SELinux或AppArmor是否可能影响SSH
	if command -v getenforce >/dev/null 2>&1; then
		SELINUX_STATUS=$(getenforce 2>/dev/null)
		if [ "$SELINUX_STATUS" = "Enforcing" ]; then
			echo "警告: SELinux处于强制模式，可能影响SSH配置"
			echo '%s' | sudo -S restorecon -R -v /root/.ssh /home/*/.ssh 2>/dev/null || true
		fi
	fi
	
	if [ -d /etc/apparmor.d ]; then
		echo "检测到AppArmor，检查SSH配置文件"
		if grep -q "sshd" /etc/apparmor.d/* 2>/dev/null; then
			echo "警告: 发现AppArmor的SSH配置，可能需要调整"
		fi
	fi
	
	# 安全地重启SSH服务
	restart_ssh() {
		local cmd="$1"
		local desc="$2"
		
		echo "尝试使用$desc重启SSH服务..."
		echo '%s' | sudo -S $cmd 2>/dev/null
		return $?
	}
	
	# 尝试多种方式重启SSH服务
	echo "正在重启SSH服务..."
	SSH_RESTARTED=0
	
	if command -v systemctl >/dev/null 2>&1; then
		restart_ssh "systemctl restart sshd" "systemctl (sshd)" && SSH_RESTARTED=1 || \
		restart_ssh "systemctl restart ssh" "systemctl (ssh)" && SSH_RESTARTED=1
	fi
	
	if [ $SSH_RESTARTED -eq 0 ] && command -v service >/dev/null 2>&1; then
		restart_ssh "service sshd restart" "service (sshd)" && SSH_RESTARTED=1 || \
		restart_ssh "service ssh restart" "service (ssh)" && SSH_RESTARTED=1
	fi
	
	if [ $SSH_RESTARTED -eq 0 ]; then
		if [ -f /etc/init.d/sshd ]; then
			restart_ssh "/etc/init.d/sshd restart" "init.d脚本 (sshd)" && SSH_RESTARTED=1
		elif [ -f /etc/init.d/ssh ]; then
			restart_ssh "/etc/init.d/ssh restart" "init.d脚本 (ssh)" && SSH_RESTARTED=1
		fi
	fi
	
	if [ $SSH_RESTARTED -eq 0 ]; then
		echo "尝试使用SIGHUP信号重启SSH服务..."
		SSHD_PID=$(pgrep -f sshd)
		if [ -n "$SSHD_PID" ]; then
			echo '%s' | sudo -S kill -HUP $SSHD_PID 2>/dev/null
			echo "向SSH进程 $SSHD_PID 发送HUP信号"
			SSH_RESTARTED=1
		else
			echo "警告: 无法找到SSH服务进程"
		fi
	fi
	
	if [ $SSH_RESTARTED -eq 1 ]; then
		echo "SSH服务重启完成"
	else
		echo "警告: SSH服务可能未成功重启，建议手动重启SSH服务"
	fi
	
	# 验证配置是否生效
	echo "等待SSH服务重新加载配置..."
	sleep 2
	
	echo "SSH配置已完成"
	echo "正在验证公钥认证配置..."
	grep -E "^PubkeyAuthentication|^RSAAuthentication|^PasswordAuthentication|^ChallengeResponseAuthentication|^PubkeyAcceptedKeyTypes|^PubkeyAcceptedAlgorithms|^AuthorizedKeysFile" "$SSHD_CONFIG_PATH" 2>/dev/null
	
	# 测试SSH配置有效性
	if command -v sshd >/dev/null 2>&1; then
		echo "正在验证SSH配置文件语法..."
		echo '%s' | sudo -S sshd -t 2>&1 || echo "警告: SSH配置文件语法检查失败，可能存在错误"
	fi
	
	exit 0
	`, password, password, password, password, password, password, disablePassword, password, password, password, password, password)

	output, err := session.CombinedOutput(configScript)
	outputStr := string(output)

	if err != nil {
		a.logError("修改SSH配置或重启服务失败: %v, 输出: %s", err, outputStr)

		// 分析输出中可能的问题
		errorMsg := "公钥上传成功，但SSH配置修改失败"
		if strings.Contains(outputStr, "permission denied") || strings.Contains(outputStr, "权限被拒绝") {
			errorMsg += ": 权限不足，请确保用户有sudo权限"
		} else if strings.Contains(outputStr, "command not found") {
			errorMsg += ": 服务器上缺少必要命令"
		} else if strings.Contains(outputStr, "找不到sshd_config") {
			errorMsg += ": 无法找到SSH配置文件"
		}

		return map[string]interface{}{
			"success": true, // 公钥已经上传，但配置修改可能失败
			"message": fmt.Sprintf("%s\n错误详情: %v\n请考虑手动修改SSH配置并重启服务", errorMsg, err),
		}
	}

	// 记录配置过程的输出
	a.logInfo("SSH配置过程: %s", outputStr)

	// 最后进行一次SSH目录检查，确认一切就绪
	finalCheckSession, err := sshClient.NewSession()
	if err == nil {
		defer finalCheckSession.Close()
		finalCheckOutput, _ := finalCheckSession.CombinedOutput("ls -la ~/.ssh && echo '===' && cat ~/.ssh/authorized_keys || echo '无法读取authorized_keys'")
		a.logInfo("最终SSH配置检查:\n%s", string(finalCheckOutput))
	}

	// 检查配置结果
	success := true
	message := "SSH配置完成，公钥上传并配置成功！现在应该可以使用SSH密钥进行免密登录了。"

	// 检查输出中的警告信息
	if strings.Contains(outputStr, "警告") || strings.Contains(outputStr, "失败") {
		message += "\n注意: 过程中有警告或部分操作失败，但公钥已成功上传。"
		if strings.Contains(outputStr, "无法找到SSH服务进程") {
			message += "\n您可能需要手动重启SSH服务使配置生效。"
		}
	}

	a.logInfo("SSH配置完成，公钥上传并配置成功")
	return map[string]interface{}{
		"success": success,
		"message": message,
	}
}

// TestKeyConnection 测试SSH连接
func (a *App) TestKeyConnection(hostname string, port string, username string, password string) map[string]interface{} {
	a.logInfo("测试SSH连接: %s@%s:%s", username, hostname, port)

	// 设置SSH客户端配置
	sshConfig := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		Timeout:         5 * time.Second, // 连接超时时间
	}

	// 创建SSH连接地址
	sshAddr := fmt.Sprintf("%s:%s", hostname, port)

	// 尝试SSH连接
	sshClient, err := ssh.Dial("tcp", sshAddr, sshConfig)
	if err != nil {
		a.logError("SSH连接失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("连接失败: %v", err),
		}
	}
	defer sshClient.Close()

	// 尝试创建一个SSH会话来验证连接
	session, err := sshClient.NewSession()
	if err != nil {
		a.logError("无法创建SSH会话: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("无法创建SSH会话: %v", err),
		}
	}
	defer session.Close()

	// 执行一个简单的命令来验证连接
	output, err := session.CombinedOutput("echo 连接测试成功")
	if err != nil {
		a.logError("执行命令失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("执行命令失败: %v", err),
		}
	}

	// 检查是否支持SFTP
	sftpClient, err := sftp.NewClient(sshClient)
	if err != nil {
		a.logError("SFTP连接失败: %v", err)
		return map[string]interface{}{
			"success": true, // SSH连接成功，但SFTP失败
			"message": fmt.Sprintf("SSH连接成功，但SFTP不可用: %v", err),
		}
	}
	defer sftpClient.Close()

	a.logInfo("SSH连接测试成功")
	return map[string]interface{}{
		"success": true,
		"message": fmt.Sprintf("连接成功: %s", strings.TrimSpace(string(output))),
	}
}

// SSHServiceStatus 检查远程SSH服务的状态
func (a *App) SSHServiceStatus(hostname string, port string, username string, password string) map[string]interface{} {
	a.logInfo("检查SSH服务状态: %s@%s:%s", username, hostname, port)

	// 设置SSH客户端配置
	sshConfig := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		Timeout:         5 * time.Second,
	}

	// 创建SSH连接地址
	sshAddr := fmt.Sprintf("%s:%s", hostname, port)

	// 尝试SSH连接
	sshClient, err := ssh.Dial("tcp", sshAddr, sshConfig)
	if err != nil {
		a.logError("SSH连接失败: %v", err)
		return map[string]interface{}{
			"sshRunning":          false,
			"passwordAuthAllowed": false,
			"pubkeyAuthAllowed":   false,
			"message":             fmt.Sprintf("SSH服务检查失败: %v", err),
		}
	}
	defer sshClient.Close()

	// 创建SSH会话用于命令执行
	session, err := sshClient.NewSession()
	if err != nil {
		a.logError("无法创建SSH会话: %v", err)
		return map[string]interface{}{
			"sshRunning":          true,
			"passwordAuthAllowed": true, // 因为我们通过密码连接成功了
			"pubkeyAuthAllowed":   false,
			"message":             "SSH服务运行中，但无法创建会话",
		}
	}
	defer session.Close()

	// 检查SSH配置文件以确定密码认证和公钥认证的状态
	output, err := session.CombinedOutput("grep -E \"^[[:space:]]*PasswordAuthentication|^[[:space:]]*PubkeyAuthentication\" /etc/ssh/sshd_config")

	// 即使无法获取配置文件信息，也能确定SSH服务在运行
	// 因为我们已经成功连接了
	var passwordAuthAllowed = true // 默认值
	var pubkeyAuthAllowed = true   // 默认值

	if err == nil {
		// 解析结果
		configStr := string(output)
		passwordAuthDisabled := strings.Contains(configStr, "PasswordAuthentication no")
		passwordAuthAllowed = !passwordAuthDisabled

		pubkeyAuthDisabled := strings.Contains(configStr, "PubkeyAuthentication no")
		pubkeyAuthAllowed = !pubkeyAuthDisabled
	}

	return map[string]interface{}{
		"sshRunning":          true,
		"passwordAuthAllowed": passwordAuthAllowed,
		"pubkeyAuthAllowed":   pubkeyAuthAllowed,
		"message":             "SSH服务正常运行",
	}
}

// OpenTerminal 打开终端并使用SSH连接到服务器
func (a *App) OpenTerminal(hostname string, port string, username string) map[string]interface{} {
	// 检查是否在短时间内重复打开相同服务器的终端
	now := time.Now()
	if a.terminalBusy || (hostname == a.lastTerminalHost && now.Sub(a.lastTerminalTime) < 5*time.Second) {
		a.logInfo("阻止重复打开终端: %s@%s:%s", username, hostname, port)
		return map[string]interface{}{
			"success": false,
			"message": "终端窗口已在打开中，请等待或使用现有窗口",
		}
	}

	// 设置终端正在打开的标志
	a.terminalBusy = true
	a.lastTerminalHost = hostname
	a.lastTerminalTime = now

	// 使用defer确保即使出错也会重置标志
	defer func() {
		// 延迟2秒重置终端状态，防止过快点击
		go func() {
			time.Sleep(2 * time.Second)
			a.terminalBusy = false
		}()
	}()

	a.logInfo("尝试打开终端连接: %s@%s:%s", username, hostname, port)

	var cmd *exec.Cmd
	var err error

	// 根据操作系统选择合适的终端命令
	switch runtime.GOOS {
	case "windows":
		// 在Windows上使用cmd，避免使用中文字符以防编码问题
		sshCmd := fmt.Sprintf("ssh %s@%s -p %s", username, hostname, port)

		// 创建一个批处理脚本用于启动SSH并保持窗口打开，使用英文避免编码问题
		tempDir := os.TempDir()
		scriptPath := filepath.Join(tempDir, "ssh_connect.bat")

		// 使用纯ASCII字符
		scriptContent := fmt.Sprintf(`@echo off
echo Connecting to %s@%s:%s ...
echo The window will stay open if the connection fails
%s
if %%ERRORLEVEL%% NEQ 0 (
    echo.
    echo SSH connection failed, error code: %%ERRORLEVEL%%
    echo Please check username, hostname and port
    echo Press any key to close...
    pause > nul
) else (
    echo.
    echo Press any key to close...
    pause > nul
)
`, username, hostname, port, sshCmd)

		err = os.WriteFile(scriptPath, []byte(scriptContent), 0755)
		if err != nil {
			a.logError("创建批处理脚本失败: %v", err)
			return map[string]interface{}{
				"success": false,
				"message": fmt.Sprintf("创建批处理脚本失败: %v", err),
			}
		}

		// 使用cmd直接运行脚本
		cmd = exec.Command("cmd.exe", "/c", "start", "cmd.exe", "/k", scriptPath)

	case "darwin":
		// 在macOS上使用Terminal.app，在脚本失败时保持窗口打开
		sshCmd := fmt.Sprintf(`ssh %s@%s -p %s || (echo "Connection failed, press Enter to close"; read)`, username, hostname, port)
		cmd = exec.Command("osascript", "-e", fmt.Sprintf(`tell app "Terminal" to do script "%s"`, sshCmd))

	case "linux":
		// 在Linux上使用终端，在脚本失败时保持窗口打开
		sshCmd := fmt.Sprintf(`ssh %s@%s -p %s; if [ $? -ne 0 ]; then echo "Connection failed, press Enter to close"; read; fi`, username, hostname, port)

		// 尝试常见的终端模拟器
		// 先检查是否有gnome-terminal
		gnomeTerminalCmd := exec.Command("which", "gnome-terminal")
		if gnomeTerminalCmd.Run() == nil {
			cmd = exec.Command("gnome-terminal", "--", "bash", "-c", sshCmd)
		} else {
			// 尝试xterm
			xtermCmd := exec.Command("which", "xterm")
			if xtermCmd.Run() == nil {
				cmd = exec.Command("xterm", "-e", sshCmd)
			} else {
				// 尝试konsole
				konsoleCmd := exec.Command("which", "konsole")
				if konsoleCmd.Run() == nil {
					cmd = exec.Command("konsole", "-e", sshCmd)
				} else {
					return map[string]interface{}{
						"success": false,
						"message": "未找到支持的终端模拟器",
					}
				}
			}
		}

	default:
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("不支持的操作系统: %s", runtime.GOOS),
		}
	}

	// 执行命令
	err = cmd.Start()
	if err != nil {
		a.logError("打开终端失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("打开终端失败: %v", err),
		}
	}

	a.logInfo("终端已打开")
	return map[string]interface{}{
		"success": true,
		"message": "终端已打开",
	}
}

// RestartSSHService 重启远程服务器上的SSH服务
func (a *App) RestartSSHService(hostname string, port string, username string, password string) map[string]interface{} {
	a.logInfo("重启SSH服务: %s@%s:%s", username, hostname, port)

	// 设置SSH客户端配置
	sshConfig := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		Timeout:         5 * time.Second,
	}

	// 创建SSH连接地址
	sshAddr := fmt.Sprintf("%s:%s", hostname, port)

	// 尝试SSH连接
	sshClient, err := ssh.Dial("tcp", sshAddr, sshConfig)
	if err != nil {
		a.logError("SSH连接失败: %v", err)
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("SSH连接失败: %v", err),
		}
	}
	defer sshClient.Close()

	// 1. 首先检查操作系统类型
	osCheckSession, err := sshClient.NewSession()
	if err != nil {
		return map[string]interface{}{
			"success": false,
			"message": "无法创建SSH会话检查操作系统类型",
		}
	}

	osCheckOutput, _ := osCheckSession.CombinedOutput("cat /etc/os-release 2>/dev/null || uname -a")
	osInfo := string(osCheckOutput)
	osCheckSession.Close()

	// 详细记录系统信息
	a.logInfo("检测到远程系统信息: %s", osInfo)

	// 2. 检查sudo权限和密码需求
	sudoSession, err := sshClient.NewSession()
	if err != nil {
		return map[string]interface{}{
			"success": false,
			"message": "无法创建SSH会话检查sudo权限",
		}
	}

	// 尝试运行sudo -l检查sudo权限
	sudoCheckOutput, sudoErr := sudoSession.CombinedOutput("echo '" + password + "' | sudo -S -l 2>&1")
	sudoInfo := string(sudoCheckOutput)
	sudoSession.Close()

	// 记录sudo权限检查结果
	if sudoErr != nil {
		a.logError("sudo权限检查失败: %v, 输出: %s", sudoErr, sudoInfo)
	} else {
		a.logInfo("sudo权限检查: %s", sudoInfo)
	}

	// 3. 检查SSH服务的名称和状态
	serviceSession, err := sshClient.NewSession()
	if err != nil {
		return map[string]interface{}{
			"success": false,
			"message": "无法创建SSH会话检查服务状态",
		}
	}

	// 尝试多种方式检查SSH服务状态
	serviceCheckCmd := `
	if command -v systemctl >/dev/null 2>&1; then
		echo "Using systemctl"
		sudo -n systemctl status sshd 2>/dev/null || sudo -n systemctl status ssh 2>/dev/null
	elif command -v service >/dev/null 2>&1; then
		echo "Using service"
		sudo -n service sshd status 2>/dev/null || sudo -n service ssh status 2>/dev/null
	else
		echo "SSH service information not available"
		ps aux | grep -E "[s]h[d]"
	fi
	`

	serviceOutput, _ := serviceSession.CombinedOutput(serviceCheckCmd)
	serviceInfo := string(serviceOutput)
	serviceSession.Close()

	// 记录SSH服务信息
	a.logInfo("SSH服务状态: %s", serviceInfo)

	// 4. 尝试重启SSH服务
	// 根据不同的情况提供多种重启命令选项
	restartSession, err := sshClient.NewSession()
	if err != nil {
		return map[string]interface{}{
			"success": false,
			"message": "无法创建SSH会话重启服务",
		}
	}
	defer restartSession.Close()

	// 构建一个详细的重启命令，带有多个回退选项，并包含详细的错误报告
	restartCmd := fmt.Sprintf(`
	echo "Attempting to restart SSH service..."
	# 首先尝试使用提供的密码执行sudo命令
	echo '%s' | sudo -S true >/dev/null 2>&1
	SUDO_STATUS=$?
	
	if [ $SUDO_STATUS -eq 0 ]; then
		echo "Sudo authentication successful"
		# 尝试使用systemctl
		if command -v systemctl >/dev/null 2>&1; then
			echo "Using systemctl to restart"
			echo '%s' | sudo -S systemctl restart sshd 2>&1 || echo '%s' | sudo -S systemctl restart ssh 2>&1
			EXIT_CODE=$?
			if [ $EXIT_CODE -eq 0 ]; then
				echo "SSH service restart successful using systemctl"
				exit 0
			else
				echo "systemctl restart failed with code $EXIT_CODE"
			fi
		fi
		
		# 尝试使用service命令
		if command -v service >/dev/null 2>&1; then
			echo "Using service command to restart"
			echo '%s' | sudo -S service sshd restart 2>&1 || echo '%s' | sudo -S service ssh restart 2>&1
			EXIT_CODE=$?
			if [ $EXIT_CODE -eq 0 ]; then
				echo "SSH service restart successful using service command"
				exit 0
			else
				echo "service restart failed with code $EXIT_CODE"
			fi
		fi
		
		# 最后一种方法 - 可能不安全，但在某些系统上有效
		echo "Trying direct method to restart SSH"
		echo '%s' | sudo -S kill -HUP $(pgrep -f sshd) 2>&1
		EXIT_CODE=$?
		if [ $EXIT_CODE -eq 0 ]; then
			echo "SSH service restart attempted using signal HUP"
			exit 0
		else
			echo "HUP signal failed with code $EXIT_CODE"
			echo "All restart methods failed"
			exit 1
		fi
	else
		echo "Failed to authenticate with sudo. Status code: $SUDO_STATUS"
		echo "Please check your password or sudo privileges"
		exit 1
	fi
	`, password, password, password, password, password, password, password, password, password, password, password, password)

	output, err := restartSession.CombinedOutput(restartCmd)
	outputStr := string(output)

	a.logInfo("重启SSH服务结果: %s", outputStr)

	if err != nil {
		// 分析输出以提供更有用的错误信息
		if strings.Contains(outputStr, "authentication") || strings.Contains(outputStr, "password") {
			return map[string]interface{}{
				"success": false,
				"message": "sudo认证失败，请检查密码或sudo权限设置",
			}
		} else if strings.Contains(outputStr, "Permission denied") {
			return map[string]interface{}{
				"success": false,
				"message": "权限被拒绝，您的账户可能没有所需的sudo权限",
			}
		} else if strings.Contains(outputStr, "command not found") {
			return map[string]interface{}{
				"success": false,
				"message": "未找到必要的命令，服务器可能缺少systemctl或service工具",
			}
		} else {
			return map[string]interface{}{
				"success": false,
				"message": fmt.Sprintf("重启失败: %v\n详细信息: %s", err, outputStr),
			}
		}
	}

	// 检查输出中的成功信息
	if strings.Contains(outputStr, "successful") {
		return map[string]interface{}{
			"success": true,
			"message": "SSH服务重启成功",
		}
	} else if strings.Contains(outputStr, "failed") || strings.Contains(outputStr, "Failed") {
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("重启命令执行完成，但可能失败: %s", outputStr),
		}
	}

	// 默认情况下假设成功
	return map[string]interface{}{
		"success": true,
		"message": "SSH服务重启命令已执行，请检查服务状态",
	}
}
